home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
xconq
/
X11.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
45KB
|
1,495 lines
/* Copyright (c) 1987, 1988 Stanley T. Shebs, University of Utah. */
/* Copyright 1988 by Chris D. Peterson, MIT. */
/* Many improvements by Tim Moore, University of Utah. */
/* This program may be used, copied, modified, and redistributed freely */
/* for noncommercial purposes, so long as this notice remains intact. */
#pragma comment(exestr, "@(#) X11.c 12.1 95/05/09 ")
/* RCS $Header: X11.c,v 1.3 88/07/19 11:10:03 shebs Exp $ */
/* Interface implementations for the X11 version of xconq. */
#include "config.h"
#include "misc.h"
#include "period.h"
#include "side.h"
#include "unit.h"
#include "map.h"
#include "global.h"
/* careful of the path of the X header files. */
#ifdef UNIX
#include <signal.h> /* needed for ^C disabling */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif /* UNIX */
/* various bitmap definitions. */
#define dots_width 16
#define dots_height 16
static char dots_bits[] = {
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#define mask_width 16
#define mask_height 16
static char mask_bits[] = {
0xe0, 0x03, 0xd8, 0x0f, 0xb4, 0x19, 0x8a, 0x21,
0x86, 0x61, 0x85, 0x41, 0x83, 0xc1, 0xff, 0xff,
0xff, 0xff, 0x83, 0xc1, 0x82, 0xa1, 0x86, 0x61,
0x84, 0x51, 0x98, 0x2d, 0xf0, 0x1b, 0xc0, 0x07};
#define curs_width 16
#define curs_height 16
static char curs_bits[] = {
0xe0, 0x03, 0x98, 0x0c, 0x84, 0x10, 0x82, 0x20,
0x82, 0x20, 0x81, 0x40, 0x81, 0x40, 0xff, 0x7f,
0x81, 0x40, 0x81, 0x40, 0x82, 0x20, 0x82, 0x20,
0x84, 0x10, 0x98, 0x0c, 0xe0, 0x03, 0x00, 0x00};
#define bomb1_width 32
#define bomb1_height 32
static char bomb1_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0x01, 0x00, 0x00, 0xf0, 0x07, 0x00,
0x00, 0xf0, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00,
0x00, 0xf8, 0x0f, 0x00, 0x00, 0xfc, 0x0f, 0x00,
0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x3f, 0x00,
0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#define bomb2_width 32
#define bomb2_height 32
static char bomb2_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,
0x00, 0xf8, 0x07, 0x00, 0x00, 0xfc, 0x0f, 0x00,
0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00,
0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
0x00, 0xfc, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00,
0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x03, 0x00,
0x00, 0xf0, 0x07, 0x00, 0x00, 0xf0, 0x07, 0x00,
0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x0f, 0x00,
0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x1f, 0x00,
0x00, 0xf8, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00,
0x00, 0xff, 0x7f, 0x00, 0xc0, 0xff, 0xff, 0x03,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#define bomb3_width 32
#define bomb3_height 32
static char bomb3_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xe2, 0xa3, 0x3f,
0x00, 0xfc, 0x1f, 0x00, 0x3c, 0xff, 0x7f, 0x7c,
0x80, 0xff, 0xff, 0x00, 0xc0, 0xff, 0xff, 0x01,
0xc0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x03,
0xe0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x03,
0xe0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x49,
0x82, 0xff, 0xff, 0x34, 0x14, 0xfe, 0x3f, 0x42,
0xe2, 0xff, 0x9f, 0x34, 0x40, 0xfe, 0x3f, 0x41,
0xbe, 0xfd, 0xdf, 0x1e, 0x00, 0xf8, 0x1f, 0x01,
0xfe, 0xfd, 0xdf, 0x7f, 0x00, 0xfc, 0x1f, 0x00,
0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00,
0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x3f, 0x00,
0x00, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0xff, 0x00,
0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
#define bomb4_width 32
#define bomb4_height 32
static char bomb4_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00,
0x00, 0x78, 0x10, 0x00, 0x00, 0x0f, 0x46, 0x00,
0x80, 0x61, 0x81, 0x00, 0xc0, 0x1c, 0x00, 0x01,
0x40, 0x02, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00,
0x20, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
0x20, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00,
0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
/* This is the name of a family of programs, so argv[0] inadequate. */
#define PROGRAMNAME "xconq"
/* Name of default font - why is this wired in? */
#define STANDARD "standard"
/* Magic number meaning that this pixmap intentionally left blank. */
#define NOPIXMAP 17
#define INFOLINES 4
#define BH 32
/* Use with caution - variable name "side" embedded! */
#define sd() ((Screeno *) side->display)
#define sdd() (((Screeno *) side->display)->disp)
typedef unsigned int unint;
/* GC rules are for different fonts etc, but not colors or bitmaps. */
typedef struct a_screen {
Display *disp;
GC gc; /* a tmp graphics context for this display */
GC flashgc; /* The gc for drawing the flash lines. */
GC textgc; /* foreground on background text */
GC icongc; /* icon graphics context */
GC invicongc; /* icon gc inverted colors. */
GC varicongc; /* This is an icon gc with variable fgcolor. */
GC unitgc; /* unit bitmap printing gc. */
GC unittextgc; /* unit text printing gc. */
GC cleargc; /* The gc to use for clearing areas. */
GC clearbitgc; /* gc for clearing bitmaps */
XFontStruct *textfont; /* font for text display */
XFontStruct *iconfont; /* utility font with assorted icons */
XFontStruct *unitfont; /* font for unit characters */
Pixmap bombpics[4]; /* mushroom clouds */
Pixmap unitpics[MAXUTYPES]; /* used instead of font sometimes */
Pixmap wbdots, bwdots; /* blue border and dotted backgrounds */
Cursor curs; /* the cursor object itself */
} Screeno;
extern int giventime;
/* Random function declarations. */
XFontStruct * open_font();
Pixmap load_bitmap();
void get_font_size();
Cursor make_cursor();
/* The array of screen objects. */
Screeno screens[MAXSIDES]; /* All the "screen objects" */
/* Values of parameters generally tied to fonts and the like. */
int hw = 20;
int hh = 22;
int hch = 17;
int margin = 2;
int bd = 1;
int helpwinlines = 1; /* size of help window */
bool rootcursor; /* true if using parent window's cursor */
/* Put in a default player, probably the invoker of the program. */
/* An empty host name will confuse everybody. */
add_default_player()
{
#ifdef UNIX
add_player(TRUE, getenv("DISPLAY"));
#endif /* UNIX */
}
/* Ignore ^C if humans in the game, do it otherwise, including when the */
/* last human player turns into a machine (this is called by option cmd). */
/* Attempts to be more clever seem to be bad news. */
init_sighandlers()
{
#ifdef UNIX
if (numhumans > 0 && !Debug) {
signal(SIGINT, SIG_IGN);
} else {
signal(SIGINT, SIG_DFL);
}
#endif /* UNIX */
}
/* Note that the open_display function syncronizes the X server when the */
/* Debug flag is set. */
open_display(side)
Side *side;
{
if (Debug) printf("starting open_display\n");
side->display = (long) &(screens[side_number(side)]);
if (Debug) printf("open_display: XopenDisplay('%s')\n", side->host);
if(NULL == (sdd() = XOpenDisplay(side->host)))
{
fprintf(stderr, "Cannot open display ('%s')\n", side->host);
exit(1);
}
if (Debug) {
XSynchronize(sdd(), TRUE);
printf("Synching the X server.\n");
}
init_cmaps(side);
side->main = XCreateSimpleWindow(sdd(), DefaultRootWindow(sdd()),
50, 3,
display_width(side), display_height(side),
3, white_color(side), black_color(side));
XSetWindowColormap(sdd(), side->main, side->cmap);
read_options(side);
if (Debug) printf("done open_display\n");
return (sdd() != NULL);
}
/* A predicate that tests whether our display can safely be written to. */
active_display(side)
Side *side;
{
return (side && side->host && !side->lost && side->display);
}
display_width(side)
Side *side;
{
return ((19 * XDisplayWidth(sdd(), DefaultScreen(sdd()))) / 20);
}
display_height(side)
Side *side;
{
return ((19 * XDisplayHeight(sdd(), DefaultScreen(sdd()))) / 20);
}
/* Most X displays have enough screen to do a world map. */
world_display(side) Side *side; { return TRUE; }
/* Could use handlers for X failures... */
/* Do misc setup thingies. */
/* Do the rigmarole to convert all those short arrays into X-approved */
/* Bitmaps. Note that this has to be for *each* display separately (!) */
/* Also get the cursor shape. If the hardware can't hack the desired */
/* cursor size, warn about it and just use the root window's cursor. */
/* 0x0 cursor specs seem to be don't cares - machine can handle any size */
/* X11 also needs gazillions of GCs, since we've got so many fonts and */
/* colors and bitmaps. */
init_misc(side)
Side *side;
{
int u, w, h;
unsigned long mask;
XGCValues values;
Pixmap mmask, mcurs, dots;
GC gc;
side->margin = margin;
side->bd = bd;
side->hw = hw;
side->hh = hh;
side->hch = hch;
mask = GCForeground | GCBackground;
values.foreground = side->fgcolor;
values.background = side->bgcolor;
gc = XCreateGC(sdd(), side->main, mask, &values);
sd()->gc = XCreateGC(sdd(), side->main, mask, &values);
sd()->flashgc = XCreateGC(sdd(), side->main, mask, &values);
sd()->textgc = XCreateGC(sdd(), side->main, mask, &values);
sd()->icongc = XCreateGC(sdd(), side->main, mask, &values);
sd()->varicongc = XCreateGC(sdd(), side->main, mask, &values);
sd()->unitgc = XCreateGC(sdd(), side->main, mask, &values);
sd()->unittextgc = XCreateGC(sdd(), side->main, mask, &values);
values.foreground = side->bgcolor;
values.background = side->fgcolor;
sd()->invicongc = XCreateGC(sdd(), side->main, mask, &values);
values.function = GXclear;
mask = GCFunction;
sd()->cleargc = XCreateGC(sdd(), side->main, mask, &values);
sd()->textfont = open_font(side, TEXTFONT, "TextFont", NULL);
get_font_size(sd()->textfont, &(side->fw), &(side->fh) );
sd()->iconfont = open_font(side, ICONFONT, "IconFont", sd()->textfont);
get_font_size(sd()->iconfont, &(side->hw), &(side->hh) );
if (period.fontname != NULL && strlen(period.fontname) > 0) {
sd()->unitfont =
open_font(side, period.fontname, "UnitFont", sd()->textfont);
get_font_size(sd()->unitfont, &(side->uw), &(side->uh) );
} else {
sd()->unitfont =
open_font(side, STANDARD, "UnitFont", sd()->textfont);
get_font_size(sd()->unitfont, &(side->uw), &(side->uh) );
}
XSetFont(sdd(), sd()->textgc, sd()->textfont->fid);
XSetFont(sdd(), sd()->icongc, sd()->iconfont->fid);
mask = GCFillStyle | GCGraphicsExposures;
values.fill_style = FillSolid;
values.graphics_exposures = FALSE;
XChangeGC(sdd(), sd()->unitgc, mask, &values);
XSetFont(sdd(), sd()->unittextgc, sd()->unitfont->fid);
XSetFont(sdd(), sd()->invicongc, sd()->iconfont->fid);
XSetFont(sdd(), sd()->varicongc, sd()->iconfont->fid);
XSetFunction(sdd(), sd()->flashgc, GXinvert);
mmask = XCreateBitmapFromData(sdd(), side->main,
mask_bits, mask_width, mask_height);
mcurs = XCreateBitmapFromData(sdd(), side->main,
curs_bits, curs_width, curs_height);
dots = XCreateBitmapFromData(sdd(), side->main,
dots_bits, dots_width, dots_height);
sd()->bombpics[0] = XCreateBitmapFromData(sdd(), side->main,
bomb1_bits, bomb1_width, bomb1_height);
sd()->bombpics[1] = XCreateBitmapFromData(sdd(), side->main,
bomb2_bits, bomb2_width, bomb2_height);
sd()->bombpics[2] = XCreateBitmapFromData(sdd(), side->main,
bomb3_bits, bomb3_width, bomb3_height);
sd()->bombpics[3] = XCreateBitmapFromData(sdd(), side->main,
bomb4_bits, bomb4_width, bomb4_height);
for_all_unit_types(u) {
if (utypes[u].bitmapname && (strlen(utypes[u].bitmapname) > 0)) {
sd()->unitpics[u] = load_bitmap(side, utypes[u].bitmapname);
} else {
utypes[u].bitmapname = NULL;
}
}
if (Debug) printf("Bitmaps stored ...\n");
sd()->wbdots = XCreatePixmap(sdd(), side->main, dots_width, dots_height,
DefaultDepth(sdd(), DefaultScreen(sdd())));
sd()->bwdots = XCreatePixmap(sdd(), side->main, dots_width, dots_height,
DefaultDepth(sdd(), DefaultScreen(sdd())));
/* Since clearbitgc has to have a depth of 1 we'll */
/* hang it off bombpics[0] */
mask = GCFunction;
values.function = GXclear;
sd()->clearbitgc = XCreateGC(sdd(), sd()->bombpics[0], mask, &values);
XSetForeground(sdd(), gc, side->fgcolor);
XSetBackground(sdd(), gc, side->bgcolor);
XSetStipple(sdd(), gc, dots);
XSetFillStyle(sdd(), gc, FillOpaqueStippled);
XFillRectangle(sdd(), sd()->wbdots, gc, 0, 0, dots_width, dots_height);
XSetForeground(sdd(), gc, side->bgcolor);
XSetBackground(sdd(), gc, side->fgcolor);
XFillRectangle(sdd(), sd()->bwdots, gc, 0, 0, dots_width, dots_height);
if (Debug) printf("Tiles stored ...\n");
rootcursor = FALSE;
XQueryBestCursor(sdd(), side->main, curs_width, curs_height, &w, &h);
if (Debug) printf("Allowed cursor shape is %dx%d\n", w, h);
if (w >= curs_width && h >= curs_height) {
sd()->curs =
make_cursor(side, mcurs, mmask, white_color(side),
black_color(side), 7, 7);
} else {
fprintf(stderr, "Warning: Can't have %dx%d cursors on \"%s\"!\n",
curs_width, curs_height, side->host);
fprintf(stderr, "Using default cursor...\n");
rootcursor = TRUE;
}
if (Debug) printf("Cursor stored ...\n");
XFreeGC(sdd(), gc);
XFreePixmap(sdd(), dots);
XFreePixmap(sdd(), mmask);
XFreePixmap(sdd(), mcurs);
}
/* Since XCreatePixmapCursor() takes XColors and not pixel values we */
/* have to look the colors associated with the foreground and */
/* background pixel values up in the color table and pass them to */
/* XCreatePixmapCursor(). */
Cursor
make_cursor(side, curs, mask, foreground, background, x, y)
Side *side;
Pixmap curs, mask;
unsigned long foreground, background;
unsigned int x, y;
{
XColor defs[2];
defs[0].pixel = foreground;
defs[1].pixel = background;
XQueryColors(sdd(), side->cmap, defs, 2);
return XCreatePixmapCursor(sdd(), curs, mask, &defs[0], &defs[1], x, y);
}
/* Since font lookup is still not smart among Xs, this is a general routine */
/* that can deal with unopenable, missing, etc, fonts, as well as the use of */
/* .Xdefaults. One of the inputs is another font that can be substituted if */
/* necessary. */
XFontStruct *
open_font(side, name, xdefault, altfont)
Side *side;
char *name, *xdefault;
XFontStruct * altfont;
{
char *firstname, *altname;
XFontStruct * font;
if ((altname = XGetDefault(sdd(), PROGRAMNAME, xdefault)) != NULL)
name = altname;
firstname = name;
if ((font = XLoadQueryFont(sdd(), name)) == NULL) {
add_font_path(side,XFONTPATH);
if ((font = XLoadQueryFont(sdd(), name)) == NULL) {
fprintf(stderr, "Can't open font \"%s\" on \"%s\"\n",
name, side->host);
if (altfont != NULL) {
fprintf(stderr, "Substituting another font...\n");
return altfont;
} else {
fprintf(stderr, "No font to substitute!!\n");
exit(1);
}
}
}
if (Debug) printf("Opened font \"%s\" ...\n", name);
return font;
}
/* Force X11 font fanciness into semblance of X10 font plainness. */
void
get_font_size(font, width, height)
XFontStruct * font;
short *width, *height;
{
#ifdef SCO_UNIX
/* this seems to work best; for some reason, the bounds width
* doesn't seem to give the right result.
*/
*width = XTextWidth(font, "12345678", 8) / 8;
*height = font->max_bounds.ascent + font->max_bounds.descent;
#else
*width = font->max_bounds.rbearing - font->min_bounds.lbearing;
*height = font->max_bounds.ascent + font->max_bounds.descent;
#endif /* SCO_UNIX */
if (Debug) {
printf("rbearing = %d lbearing = %d\n",
(int)font->max_bounds.rbearing, (int)font->min_bounds.lbearing);
printf("returning font size %d %d\n", (int)*width, (int)*height);
}
}
/* Try to load a bitmap of the given name - can be either X11-only (.b11) */
/* or X10 (.b) bitmaps, but prefer X11 flavor. */
Pixmap
load_bitmap(side, name)
Side *side;
char *name;
{
int w, h, junk, a;
Pixmap rslt;
make_pathname(NULL, name, "b11", spbuf);
a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
if (a == BitmapSuccess) return rslt;
make_pathname(XCONQLIB, name, "b11", spbuf);
a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
if (a == BitmapSuccess) return rslt;
make_pathname(XCONQLIB, name, "b", spbuf);
a = XReadBitmapFile(sdd(), side->main, spbuf, &w, &h, &rslt, &junk, &junk);
if (a == BitmapSuccess) return rslt;
fprintf(stderr, "Bitmap name \"%s\" not found anywhere!\n", name);
return (-1);
}
/* This routine has to be able to cope with window managers constraining */
/* size. Actually, the main window was already opened when the display */
/* was opened, so the name is not quite accurate! */
create_main_window(side)
Side *side;
{
Pixmap dots;
XSizeHints hints;
XStoreName(sdd(), side->main, PROGRAMNAME);
dots = (side->bonw ? sd()->bwdots : sd()->wbdots);
XSetWindowBackgroundPixmap(sdd(), side->main, dots);
hints.width = side->mw;
hints.height = side->mh;
hints.min_width = side->mw;
hints.min_height = side->mh;
hints.flags = PSize|PMinSize;
XSetNormalHints(sdd(), side->main, &hints);
}
/* Help window is not necessarily a subwindow, though it might be sometimes. */
create_help_window(side)
Side *side;
{
helpwinlines =
max(45, (24 + period.numrtypes + period.numttypes + period.numutypes));
side->help = XCreateSimpleWindow(sdd(), DefaultRootWindow(sdd()),
0, 0, 80*side->fw+1,
helpwinlines*side->fh+1,
1, side->fgcolor, side->bgcolor);
XStoreName(sdd(), side->help, "xconq-help");
XSetWindowColormap(sdd(), side->help, side->cmap);
}
/* Subwindow creator. If name is not null, create a split window. */
create_window(side, x, y, w, h, name)
Side *side;
int x, y, w, h;
char *name;
{
int win;
win = XCreateSimpleWindow(sdd(),
name ? DefaultRootWindow(sdd()) : side->main,
x, y, w, h, 1, side->fgcolor, side->bgcolor);
if (name)
XStoreName(sdd(), win, name);
XSetWindowColormap(sdd(), win, side->cmap);
return win;
}
/* Do little things necesary to make it all go, in this case mapping all */
/* the windows (except help win). */
fixup_windows(side)
Side *side;
{
XMapWindow(sdd(), side->main);
XMapSubwindows(sdd(), side->main);
if (side->split) {
XMapWindow(sdd(), side->state);
XMapWindow(sdd(), side->map);
XMapWindow(sdd(), side->world);
}
if (!giventime) XUnmapWindow(sdd(), side->clock);
if (!rootcursor) XDefineCursor(sdd(), side->map, sd()->curs);
}
/* Specify the sorts of input that will be allowed - main window needs to */
/* see mouse buttons so unit type selection works right. */
enable_input(side)
Side *side;
{
if (side->split) {
XSelectInput(sdd(), side->main,
KeyPressMask|ExposureMask|StructureNotifyMask);
XSelectInput(sdd(), side->map,
KeyPressMask|ButtonPressMask|ExposureMask|StructureNotifyMask);
XSelectInput(sdd(), side->state,
KeyPressMask|ButtonPressMask|ExposureMask);
}
else {
XSelectInput(sdd(), side->main, KeyPressMask|ExposureMask);
XSelectInput(sdd(), side->map, ButtonPressMask|ExposureMask);
XSelectInput(sdd(), side->state, ButtonPressMask|ExposureMask);
}
XSelectInput(sdd(), side->help, KeyPressMask|ExposureMask);
XSelectInput(sdd(), side->msg, ExposureMask);
XSelectInput(sdd(), side->info, ExposureMask);
XSelectInput(sdd(), side->prompt, ExposureMask);
XSelectInput(sdd(), side->timemode, ExposureMask);
XSelectInput(sdd(), side->clock, ExposureMask);
XSelectInput(sdd(), side->sides, ExposureMask);
XSelectInput(sdd(), side->world, ExposureMask);
}
/* Move windows and change their sizes to correspond with the new sizes of */
/* viewports, etc */
reset_misc(side)
Side *side;
{
Pixmap dots;
XSizeHints hints;
XGCValues values;
unsigned int gcmask;
dots = (side->bonw ? sd()->bwdots : sd()->wbdots);
XResizeWindow(sdd(), side->main, side->mw, side->mh);
hints.width = side->mw; hints.height = side->mh;
hints.min_width = side->mw; hints.min_height = side->mh;
hints.flags = PSize|PMinSize;
XSetNormalHints(sdd(), side->main, &hints);
XSetWindowBackgroundPixmap(sdd(), side->main, dots);
XSetWindowBackground(sdd(), side->msg, side->bgcolor);
XSetWindowBackground(sdd(), side->info, side->bgcolor);
XSetWindowBackground(sdd(), side->prompt, side->bgcolor);
XSetWindowBackground(sdd(), side->map, side->bgcolor);
XSetWindowBackground(sdd(), side->timemode, side->bgcolor);
XSetWindowBackground(sdd(), side->clock, side->bgcolor);
XSetWindowBackground(sdd(), side->state, side->bgcolor);
XSetWindowBackground(sdd(), side->help, side->bgcolor);
XSetWindowBackground(sdd(), side->sides, side->bgcolor);
XSetWindowBackground(sdd(), side->world, side->bgcolor);
XSetWindowBorder(sdd(), side->msg, side->fgcolor);
XSetWindowBorder(sdd(), side->info, side->fgcolor);
XSetWindowBorder(sdd(), side->prompt, side->fgcolor);
XSetWindowBorder(sdd(), side->map, side->fgcolor);
XSetWindowBorder(sdd(), side->timemode, side->fgcolor);
XSetWindowBorder(sdd(), side->clock, side->fgcolor);
XSetWindowBorder(sdd(), side->state, side->fgcolor);
XSetWindowBorder(sdd(), side->help, side->fgcolor);
XSetWindowBorder(sdd(), side->sides, side->fgcolor);
XSetWindowBorder(sdd(), side->world, side->fgcolor);
gcmask = GCForeground | GCBackground;
values.foreground = side->fgcolor;
values.background = side->bgcolor;
XChangeGC(sdd(), sd()->gc, gcmask, &values);
XChangeGC(sdd(), sd()->flashgc, gcmask, &values);
XChangeGC(sdd(), sd()->textgc, gcmask, &values);
XChangeGC(sdd(), sd()->icongc, gcmask, &values);
XChangeGC(sdd(), sd()->unitgc, gcmask, &values);
values.foreground = side->bgcolor;
values.background = side->fgcolor;
XChangeGC(sdd(), sd()->invicongc, gcmask, &values);
}
/* Alter the size and position of a window. */
change_window(side, win, x, y, w, h)
Side *side;
Window win;
int x, y, w, h;
{
unsigned int mask;
XWindowChanges changes;
if (active_display(side)) {
if (x >= 0) {
if (w >= 0) {
mask = CWX | CWY | CWWidth | CWHeight;
changes.x = x; changes.y = y;
changes.width = w; changes.height = h;
} else {
mask = CWX | CWY;
changes.x = x; changes.y = y;
}
} else {
mask = CWWidth | CWHeight;
changes.width = w; changes.height = h;
}
}
XConfigureWindow(sdd(), win, mask, &changes);
}
/* Return the number of colors - this is used to guess about monochromeness. */
display_colors(side)
Side *side;
{
return XDisplayCells(sdd(), DefaultScreen(sdd()));
}
white_color(side)
Side *side;
{
/* return request_color(side,"white");*/
return WhitePixel(sdd(), DefaultScreen(sdd()));
}
black_color(side)
Side *side;
{
/* return request_color(side,"black");*/
return BlackPixel(sdd(), DefaultScreen(sdd()));
}
/* Get a color set up and warn if not getting what was asked for. */
long
request_color(side, name)
Side *side;
char *name;
{
XColor c, avail;
if (Debug) printf("Allocating %s\n", name);
XAllocNamedColor(sdd(), side->cmap, name, &avail, &c);
if ( abs(c.red - avail.red) >= COLOR_DIFF ||
abs(c.green - avail.green) >= COLOR_DIFF ||
abs(c.blue - avail.blue) >= COLOR_DIFF ) {
fprintf(stderr, "Warning: %s color (%d) not exact on \"%s\"!\n",
name, c.pixel, side->host);
fprintf(stderr, "Is %d %d %d instead of %d %d %d\n",
avail.red, avail.green, avail.blue, c.red, c.green, c.blue);
}
return avail.pixel;
}
/* Main funnel for input returns both mouse and keyboard events, and maybe */
/* other kinds eventually. Some events like window exposure are handled */
/* strictly locally. */
get_input()
{
#ifdef SELECT2
int i, mask;
Side *side, *asides[32];
mask = 0;
for_all_sides(side) {
if (active_display(side)) {
mask |= (1 << ConnectionNumber(sdd()));
asides[ConnectionNumber(sdd())] = side;
while (XPending(sdd()) > 0) {
process_events(side);
}
side->lasttime = time(0);
}
}
if (Debug) {
printf("Waiting for input from ");
for_all_sides(side)
if (active_display(side)) printf("%s ", side->host);
printf("\n");
}
if (select(32, &mask, 0, 0, 0) < 0) {
fprintf(stderr, "error in select!\n");
abort();
} else {
for (i = 0; i < 32; ++i) {
if (mask & (1 << i)) {
process_events(asides[i]);
asides[i]->timeleft -= (time(0) - asides[i]->lasttime);
update_clock(asides[i]);
}
}
}
#else
extern Side *curside;
/* No simultaneity, but there's no portable way to do it, sigh */
if (active_display(curside) && humanside(curside)) {
if (Debug) printf("Waiting for input from %s\n", curside->host);
process_events(curside);
}
#endif /* SELECT2 */
}
/* Look at a single event and fill the request structure appropriately. */
process_events(side)
Side *side;
{
XEvent evt;
char buf[BUFSIZE];
int nchar, rawx, rawy;
int win;
unsigned int junk;
side->reqtype = GARBAGE;
XNextEvent(sdd(), &evt);
switch (evt.type) {
case KeyPress:
nchar = XLookupString(&evt, buf, BUFSIZE, NULL, NULL);
if (nchar > 0) {
side->reqtype = KEYBOARD;
side->reqch = *buf;
if (Debug) printf("Host %s returns key '%c'\n",
side->host, side->reqch);
}
break;
case ButtonPress:
win = evt.xbutton.window;
if (win == side->map) {
rawx = evt.xbutton.x; rawy = evt.xbutton.y;
side->reqtype = MAPPOS;
deform(side, rawx, rawy, &(side->reqx), &(side->reqy));
if (Debug) printf("Host %s returns map %d %d\n",
side->host, side->reqx, side->reqy);
} else if (win == side->state) {
rawx = evt.xbutton.x; rawy = evt.xbutton.y;
side->reqtype = UNITTYPE;
side->requtype = rawy / max(side->hh, side->fh);
if (Debug) printf("Host %s returns unit type %d\n",
side->host, side->requtype);
}
break;
case Expose:
win = evt.xexpose.window;
/* if this is the first expose, install our colormap
* (if we need to)
*/
if (side->InstallCmap) {
side->InstallCmap = 0;
XInstallColormap(sdd(), side->cmap);
}
/* get rid of all other Expose events on queue */
while (XCheckTypedWindowEvent(sdd(), win, Expose, &evt));
/* don't need to check which window got event,
* because we take care of that with the
* event masks.
*/
clear_window(side, win);
if (win == side->map)
show_map(side);
else if (win == side->state)
show_state(side);
else if (win == side->world)
show_world(side);
else if (win == side->msg)
show_note(side);
else if (win == side->info)
show_info(side);
else if (win == side->prompt)
show_prompt(side);
else if (win == side->sides)
show_all_sides(side);
else if (win == side->timemode)
show_timemode(side);
else if (win == side->clock)
show_clock(side);
else if (win == side->help) {
side->reqch = '\014';
x_help(side); /* redraw help window */
}
flush_output(side);
if (Debug) printf("Host %s exposes itself\n", side->host);
return FALSE;
break;
case ConfigureNotify:
win = evt.xexpose.window;
/* window has been resized */
if (win == side->map) {
undraw_box(side);
side->vw = evt.xconfigure.width / side->hw;
side->vh = evt.xconfigure.height / side->hch;
side->vw2 = side->vw / 2;
side->vh2 = side->vh / 2;
/* flush_input(side);*/
set_sizes(side); /* adjust viewport */
/* count on exposure event to draw map */
draw_box(side);
}
else if (win == side->main) {
int sy, sdy;
int remain;
remain = side->fh * (INFOLINES + 1) + 3 * side->bd;
side->nh = (evt.xconfigure.height - remain) / side->fh;
side->nh = min(side->nh, MAXNOTES);
side->nh = max(1, side->nh);
set_sizes(side);
sy = 0; sdy = side->nh * side->fh;
change_window(side, side->msg, 0, sy, side->lw, sdy);
sy += sdy + side->bd; sdy = INFOLINES * side->fh;
change_window(side, side->info, 0, sy, side->lw, sdy);
sy += sdy + side->bd; sdy = 1 * side->fh;
change_window(side, side->prompt, 0, sy, side->lw, sdy);
change_window(side, side->timemode,
side->lw + side->fw, side->th - 4 * side->fh, -1, -1);
change_window(side, side->sides, side->lw+1, 0, -1, -1);
/* count on expose to draw all windows */
}
break;
case DestroyNotify:
case CirculateNotify:
case GravityNotify:
case MapNotify:
case ReparentNotify:
case UnmapNotify:
break;
default:
#if 0
case_panic("event type", evt.type);
#endif
break;
}
}
/* Freese everything until given side supplies input, use sparingly. */
freeze_wait(side)
Side *side;
{
XEvent evt;
char buf[BUFSIZE];
int nchar;
if (Debug) printf("Waiting for a %s event\n", side->host);
flush_input(side);
while(TRUE) {
XNextEvent(sdd(), &evt);
if (evt.type == KeyPress) {
nchar = XLookupString(&evt, buf, BUFSIZE, NULL, NULL);
if (nchar > 0)
return *buf;
else
return '\0';
}
}
}
/* Get rid of extra key/mouse clicks. */
flush_input(side)
Side *side;
{
XEvent evt;
/* if (humanside(side)) XSync(sdd(), TRUE);*/
if (humanside(side)) {
while (XCheckTypedWindowEvent(sdd(), side->main, KeyPress, &evt));
while (XCheckTypedWindowEvent(sdd(), side->help, KeyPress, &evt));
while (XCheckTypedWindowEvent(sdd(), side->map, ButtonPress, &evt));
while (XCheckTypedWindowEvent(sdd(), side->state, ButtonPress, &evt));
XSync(sdd(), FALSE);
}
}
/* Trivial abstraction - sometimes other routines like to ensure all output */
/* actually on the screen. */
flush_output(side)
Side *side;
{
if (humanside(side)) XFlush(sdd());
}
/* General window clearing. */
clear_window(side, win)
Side *side;
Window win;
{
XClearWindow(sdd(), win);
}
/* Draw a single horizontal constant-color bar on the world map. If part */
/* would not be drawn because of the map's obliqueness, cut it in two and */
/* wrap one of the pieces around. */
draw_bar(side, x, y, len, color)
Side *side;
int x, y, len, color;
{
int sx1, sx2, sy, sww;
w_xform(side, x, y, &sx1, &sy);
w_xform(side, x + len, y, &sx2, &sy);
sww = side->mm * world.width;
XSetFillStyle(sdd(), sd()->gc, FillSolid);
XSetForeground(sdd(), sd()->gc, color);
if (sx1 < sww && sx2 >= sww) {
XFillRectangle(sdd(), side->world, sd()->gc,
sx1, sy, (unint) sww - sx1, (unint) side->mm);
XFillRectangle(sdd(), side->world, sd()->gc,
0, sy, (unint) sx2 - sww, (unint) side->mm);
} else {
sx1 %= sww;
sx2 %= sww;
XFillRectangle(sdd(), side->world, sd()->gc,
sx1, sy, (unint) sx2 - sx1, (unint) side->mm);
}
#ifdef STUPIDFLUSH
XFlush(sdd());
#endif /* STUPIDFLUSH */
}
/* Invert the outline box on the world map. This is a little tricky, */
/* because we want the lines to run through the middle of the world's */
/* hexes, and because the line drawn should not overlap (or the overlaps */
/* will be doubly inverted and look strange). */
invert_box(side, vcx, vcy)
Side *side;
int vcx, vcy;
{
int x1, y1, x2, y2, sx1, sy1, sx2, sy2, mm2 = side->mm/2;
x1 = vcx - side->vw2 + side->vh2/2; y1 = vcy - side->vh2;
x2 = vcx + side->vw2 - side->vh2/2; y2 = vcy + side->vh2;
w_xform(side, x1, y1, &sx1, &sy1);
w_xform(side, x2, y2, &sx2, &sy2);
sx1 += mm2; sy1 -= mm2; sx2 += mm2; sy2 += mm2;
XSetFunction(sdd(), sd()->gc, GXinvert);
/* is this next call really necessary? */
XSetLineAttributes(sdd(), sd()->gc, 1, LineSolid, CapButt, JoinMiter);
XDrawLine(sdd(), side->world, sd()->gc, sx1, sy1, sx2, sy1);
XDrawLine(sdd(), side->world, sd()->gc, sx2, sy1-1, sx2, sy2+1);
XDrawLine(sdd(), side->world, sd()->gc, sx2, sy2, sx1, sy2);
XDrawLine(sdd(), side->world, sd()->gc, sx1, sy2+1, sx1, sy1-1);
XSetFunction(sdd(), sd()->gc, GXcopy);
}
/* This interfaces higher-level drawing decisions to the rendition of */
/* individual pieces of display. */
draw_terrain_row(side, sx, sy, buf, len, color)
Side *side;
int sx, sy, len, color;
char *buf;
{
sy += sd()->iconfont->max_bounds.ascent;
XSetForeground(sdd(), sd()->icongc, color);
XDrawString(sdd(), side->map, sd()->icongc, sx, sy, buf, len);
#ifdef STUPIDFLUSH
XFlush(sdd());
#endif /* STUPIDFLUSH */
}
/* Flash a pair of lines up, slow enough to draw the eye, but not so slow */
/* as to get in the way. */
flash_position(side, sx, sy, tm)
Side *side;
int sx, sy, tm;
{
int sx1, sy1, sx2, sy2;
if (tm > 0) {
sx1 = sx - 50 + side->hw/2; sy1 = sy + 50 + side->hch/2;
sx2 = sx + 50 + side->hw/2; sy2 = sy - 50 + side->hch/2;
XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy1, sx2, sy2);
XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy2, sx2, sy1);
flush_output(side);
nap(tm);
XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy1, sx2, sy2);
XDrawLine(sdd(), side->map, sd()->flashgc, sx1, sy2, sx2, sy1);
}
}
/* The "cursor icon" is just a pair of special chars - nothing to do with */
/* X's notion of cursors. */
draw_cursor_icon(side, sx, sy)
Side *side;
int sx, sy;
{
sy += sd()->iconfont->max_bounds.ascent;
XDrawString(sdd(), side->map, sd()->invicongc, sx, sy, "[", 1);
XSetForeground(sdd(), sd()->icongc, side->fgcolor);
XDrawString(sdd(), side->map, sd()->icongc, sx, sy, "]", 1);
}
/* Draw the icon for a hex (given as a char). */
draw_hex_icon(side, win, sx, sy, color, ch)
Side *side;
Window win;
int sx, sy, color;
char ch;
{
XSetForeground(sdd(), sd()->varicongc, color);
sy += sd()->iconfont->max_bounds.ascent;
XDrawString(sdd(), win, sd()->varicongc, sx, sy, &ch, 1);
}
/* Draw the number of an unfriendly side (never called for own units). */
draw_side_number(side, win, sx, sy, n, color)
Side *side;
Window win;
int sx, sy, n, color;
{
char ch = n + '0';
if (n >= 0) {
XSetForeground(sdd(), sd()->varicongc, color);
sy += sd()->iconfont->max_bounds.ascent;
XDrawString(sdd(), win, sd()->varicongc, sx, sy, &ch, 1);
}
}
draw_blast_icon(side, win, sx, sy, type, color)
Side *side;
Window win;
int sx, sy, color;
char type;
{
char buf[1];
XSetForeground(sdd(), sd()->varicongc, color);
buf[0] = type;
sy += sd()->iconfont->max_bounds.ascent;
XDrawString(sdd(), win, sd()->varicongc, sx, sy, buf, 1);
}
/* Flash the player's screen in an unmistakable way. */
invert_whole_map(side)
Side *side;
{
int sw = side->vw * side->hw, sh = side->vh * side->hh;
/* GC needs to be set for inverted drawing */
XSetFunction(sdd(), sd()->gc, GXinvert);
XFillRectangle(sdd(), side->map, sd()->gc, 0, 0, sw, sh);
XSetFunction(sdd(), sd()->gc, GXcopy);
flush_output(side);
}
/* Draw just one of the mushroom cloud shapes. */
draw_mushroom(side, x, y, i)
Side *side;
int x, y, i;
{
int sx, sy;
int color;
color = ((side->monochrome || i == 3) ? side->fgcolor : side->bgcolor);
xform(side, unwrap(side, x), y, &sx, &sy);
XSetForeground(sdd(), sd()->unitgc, color);
XSetClipMask(sdd(), sd()->unitgc, sd()->bombpics[i]);
XSetClipOrigin(sdd(), sd()->unitgc, sx-BH/4, sy-BH/2);
XFillRectangle(sdd(), side->map, sd()->unitgc, sx-BH/4, sy-BH/2, BH, BH);
flush_output(side);
}
/* Confirm that we can indeed do bar graph displays. */
bar_graphs(side) Side *side; { return TRUE; }
/* Do yet another X-toolkit-type function. This draws a bar graph. */
draw_graph(side, number, amount, total, critical, title)
Side *side;
int number, amount, total, critical;
{
int boxwidth, boxheight, boxoffset, boxleft, barwidth, barheight;
if (total > 0) {
boxwidth = 5*side->fw;
boxheight = (INFOLINES-1)*side->fh - 2*side->margin;
boxoffset = side->margin;
boxleft = 30*side->fw + number * boxwidth;
barwidth = boxwidth / 3;
barheight = (boxheight * amount) / total;
XSetForeground(sdd(), sd()->gc, side->fgcolor);
XFillRectangle(sdd(), side->info, sd()->gc,
boxleft + boxwidth/3 - 1, boxoffset - 1,
barwidth + 2, boxheight + 2);
XSetForeground(sdd(), sd()->gc, side->bgcolor);
XFillRectangle(sdd(), side->info, sd()->gc,
boxleft + boxwidth/3, boxoffset,
barwidth, boxheight);
if ( amount > critical)
XSetForeground(sdd(), sd()->gc, side->goodcolor);
else
XSetForeground(sdd(), sd()->gc, side->badcolor);
XFillRectangle(sdd(), side->info, sd()->gc,
boxleft + boxwidth/3, boxoffset + boxheight - barheight,
barwidth, barheight);
draw_text(side, side->info,
boxleft+(boxwidth-strlen(title)*side->fw)/2,
(INFOLINES-1)*side->fh, title, side->fgcolor);
}
}
/* Splash a unit image (either bitmap or font char) onto some window. */
draw_unit_icon(side, win, x, y, u, color)
Side *side;
Window win;
int x, y, u, color;
{
char buf[1];
y += 3; /* fudge factor to make x11 look */
x += 2; /* like X10 (ugh). */
if (utypes[u].bitmapname != NULL ) {
XSetForeground(sdd(), sd()->unitgc, color);
XSetClipMask(sdd(), sd()->unitgc, sd()->unitpics[u]);
XSetClipOrigin(sdd(), sd()->unitgc, x, y);
XFillRectangle(sdd(), win, sd()->unitgc, x, y, side->uw, side->uh);
} else {
XSetForeground(sdd(), sd()->unittextgc, color);
buf[0] = utypes[u].uchar;
y += sd()->unitfont->max_bounds.ascent;
XDrawString(sdd(), win, sd()->unittextgc, x, y, buf, 1);
}
}
/* General text drawer. */
draw_text(side, win, x, y, str, color)
Side *side;
Window win;
int x, y, color;
char *str;
{
y += sd()->textfont->max_bounds.ascent;
if (color != side->bgcolor) {
XSetForeground(sdd(), sd()->textgc, color);
XDrawImageString(sdd(), win, sd()->textgc, x, y, str, strlen(str));
} else {
XSetForeground(sdd(), sd()->textgc, side->bgcolor);
XSetBackground(sdd(), sd()->textgc, side->fgcolor);
XDrawImageString(sdd(), win, sd()->textgc, x, y, str, strlen(str));
XSetBackground(sdd(), sd()->textgc, side->bgcolor);
}
#ifdef STUPIDFLUSH
XFlush(sdd());
#endif /* STUPIDFLUSH */
}
/* Draw a line through some side's title. */
draw_scratchout(side, pos)
Side *side;
int pos;
{
XSetForeground(sdd(), sd()->textgc, side->fgcolor);
XDrawLine(sdd(), side->sides, sd()->textgc, 0, pos, 30*side->fw, pos);
}
/* Beep the beeper! */
beep(side)
Side *side;
{
XBell(sdd(), DefaultScreen(sdd()));
}
/* Little routines to pop up the help window and make it go away again */
/* They only get called when display is in use. */
reveal_help(side)
Side *side;
{
XEvent evt;
XMapWindow(sdd(), side->help);
/* wait until this window is exposed to return. */
XWindowEvent(sdd(), side->help, ExposureMask, &evt);
return TRUE;
}
conceal_help(side)
Side *side;
{
XUnmapWindow(sdd(), side->help);
flush_output(side);
}
/* Shut a single display down, but only if there's one to operate on. */
/* Hit the display slot, for safety. */
close_display(side)
Side *side;
{
XCloseDisplay(sdd());
side->display = (long) NULL;
}
/* read options from server resource manager */
read_options(side)
Side *side;
{
char *option;
option = XGetDefault(sdd(), PROGRAMNAME, "Split");
side->split = parse_boolean(option);
option = XGetDefault(sdd(), PROGRAMNAME, "Graph");
side->graphical = parse_boolean(option);
option = XGetDefault(sdd(), PROGRAMNAME, "DisplayMode");
if (option)
side->showmode = atoi(option) % 4;
option = XGetDefault(sdd(), PROGRAMNAME, "Inverse");
side->bonw = parse_boolean(option);
option = XGetDefault(sdd(), PROGRAMNAME, "Monochrome");
side->monochrome = parse_boolean(option);
option = XGetDefault(sdd(), PROGRAMNAME, "InstallCmap");
side->InstallCmap = parse_boolean(option);
option = XGetDefault(sdd(), PROGRAMNAME, "NoticeLines");
if (option)
side->nh = atoi(option);
option = XGetDefault(sdd(), PROGRAMNAME, "MapWidth");
if (option) {
side->vw = atoi(option);
side->vw = min( max(side->vw, MINWIDTH), world.width);
}
option = XGetDefault(sdd(), PROGRAMNAME, "MapHeight");
if (option) {
side->vh = atoi(option);
side->vh = min( max(side->vh, MINHEIGHT), world.height);
}
}
/* parse a boolean string */
int
parse_boolean(string)
char *string;
{
if (string == 0)
return 0;
if (strcmp(string, "yes") == 0 ||
strcmp(string, "on") == 0 ||
strcmp(string, "true") == 0)
return 1;
else
return 0;
}
init_cmaps(side)
Side *side;
{
int i;
unsigned long black, white;
unsigned long *pixels;
XColor color_def, rgb_def;
Visual *visual;
side->cmap = DefaultColormap(sdd(), DefaultScreen(sdd()));
if (check_colors(side)) {
if (Debug) printf("xconq: using default colormap\n");
return TRUE; /* use default colormap */
}
if (Debug) printf("xconq: making new colormap\n");
visual = DefaultVisual(sdd(),DefaultScreen(sdd()));
side->cmap = XCreateColormap(sdd(), DefaultRootWindow(sdd()),
visual, AllocNone);
pixels = (unsigned long *)
malloc( sizeof(unsigned long) * visual->map_entries);
XAllocColorCells( sdd(), side->cmap, FALSE, 0, 0,
pixels, visual->map_entries);
white = WhitePixel(sdd(), DefaultScreen(sdd()));
black = BlackPixel(sdd(), DefaultScreen(sdd()));
XStoreNamedColor(sdd(), side->cmap, "white", white,
DoRed | DoGreen | DoBlue);
XStoreNamedColor(sdd(), side->cmap, "black", black,
DoRed | DoGreen | DoBlue);
for( i=0; i < visual->map_entries; i++) {
if (i == black || i == white)
continue;
*pixels = i;
XFreeColors(sdd(), side->cmap, pixels, 1, 0);
}
free(pixels);
return TRUE;
}
check_colors(side)
Side *side;
{
int i;
long colors[MAX_COLORS];
long planes;
for(i=MAX_COLORS; i>=MIN_COLORS; i--) {
if (XAllocColorCells(sdd(), side->cmap, FALSE, &planes, 0,
colors, i))
break;
}
if (i >= MIN_COLORS) {
XFreeColors(sdd(), side->cmap, colors, i, 0);
return i;
}
else {
return 0;
}
}
/* Completely redo a screen, making no assumptions about appearance. */
/* This one is used frequently, especially when a window is exposed. */
redraw(side)
Side *side;
{
XEvent report;
if (active_display(side)) {
report.xexpose.type = Expose;
report.xexpose.display = sdd();
report.xexpose.window = side->main;
report.xexpose.x = report.xexpose.y =
report.xexpose.width = report.xexpose.height = 1;
expose(side,&report,side->main);
expose(side,&report,side->map);
expose(side,&report,side->world);
expose(side,&report,side->state);
expose(side,&report,side->msg);
expose(side,&report,side->info);
expose(side,&report,side->prompt);
expose(side,&report,side->sides);
expose(side,&report,side->timemode);
expose(side,&report,side->clock);
expose(side,&report,side->help);
flush_output(side);
flush_input(side);
}
}
static
expose(side,event,window)
Side *side;
XEvent *event;
Window window;
{
int cc;
event->xexpose.window = window;
cc = XSendEvent(sdd(),window,False,ExposureMask,event);
}
add_font_path(side,newelement)
Side *side;
char *newelement;
{
char **fontpath, **newpath;
int i,npaths;
fontpath = XGetFontPath(sdd(), &npaths);
newpath = (char **) malloc((npaths+1) * (sizeof(char *)));
for(i=0;i<npaths;i++) {
newpath[i] = fontpath[i];
}
newpath[i] = newelement;
XSetFontPath(sdd(),newpath,npaths+1);
free(newpath);
if (fontpath)
XFreeFontPath(fontpath);
}